import { Injectable, NotFoundException } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { InjectRepository } from '@nestjs/typeorm'
import * as tencentcloud from 'tencentcloud-sdk-nodejs'
import { Repository } from 'typeorm'
import { IOcrConfig, ocrRegToken } from '~/config/ocr.config'
import { CreateOcrTaskDto } from '../dto/create-ocr-task.dto'
import { OcrQueryDto } from '../dto/ocr-query.dto'
import { OcrTaskEntity } from '../entities/ocr-task.entity'
import { OcrTaskPaginationResult, OcrTaskResult, OcrTaskStatus, OcrTaskType, TencentOcrResponse } from '../interfaces/ocr.interface'

@Injectable()
export class OcrService {
  private readonly ocrConfig: IOcrConfig

  constructor(
    private readonly configService: ConfigService,
    @InjectRepository(OcrTaskEntity)
    private readonly ocrTaskRepository: Repository<OcrTaskEntity>,
  ) {
    this.ocrConfig = this.configService.get(ocrRegToken)
  }

  /**
   * 创建腾讯云OCR任务
   */
  async createTencentOcrTask(createOcrTaskDto: CreateOcrTaskDto): Promise<OcrTaskResult> {
    const { url, taskType = OcrTaskType.TENCENT, page = 0, languageType = 'zh', isPdf = false } = createOcrTaskDto

    // 创建任务记录
    const ocrTask = this.ocrTaskRepository.create({
      url,
      page,
      taskType,
      status: OcrTaskStatus.NOT_STARTED,
    })
    await this.ocrTaskRepository.save(ocrTask)

    try {
      // 调用腾讯云OCR接口创建任务
      const OcrClient = tencentcloud.ocr.v20181119.Client
      const clientConfig = {
        credential: {
          secretId: this.ocrConfig.accessKeyId,
          secretKey: this.ocrConfig.accessKeySecret,
        },
        region: 'ap-guangzhou', // 根据实际需求设置区域
        profile: {
          httpProfile: {
            endpoint: 'ocr.tencentcloudapi.com',
          },
        },
      }

      const client = new OcrClient(clientConfig)
      const params = {
        ImageUrl: url,
        LanguageType: languageType,
        IsPdf: isPdf,
        PdfPageNumber: isPdf ? page : 0,
      }

      // 调用腾讯云接口创建识别任务
      const data = await client.GeneralBasicOCR(params) as TencentOcrResponse

      // 保存OCR识别结果
      const ocrJson = JSON.stringify(data)

      // 更新任务状态和任务ID
      await this.ocrTaskRepository.update(ocrTask.id, {
        taskId: data.RequestId,
        ocrJson,
        status: OcrTaskStatus.COMPLETED,
      })

      return {
        id: ocrTask.id,
        taskId: data.RequestId,
        url,
        status: OcrTaskStatus.COMPLETED,
      }
    }
    catch (error) {
      // 更新任务状态为失败
      await this.ocrTaskRepository.update(ocrTask.id, {
        status: OcrTaskStatus.FAILED,
      })

      throw new Error(`创建OCR任务失败: ${error.message}`)
    }
  }

  /**
   * 根据ID查询OCR任务
   */
  async findById(id: number): Promise<OcrTaskEntity> {
    const task = await this.ocrTaskRepository.findOne({ where: { id, isDelete: 0 } })
    if (!task) {
      throw new NotFoundException(`ID为${id}的OCR任务不存在`)
    }
    return task
  }

  /**
   * 根据任务ID查询OCR任务
   */
  async findByTaskId(taskId: string): Promise<OcrTaskEntity> {
    const task = await this.ocrTaskRepository.findOne({ where: { taskId, isDelete: 0 } })
    if (!task) {
      throw new NotFoundException(`任务ID为${taskId}的OCR任务不存在`)
    }
    return task
  }

  /**
   * 查询OCR任务列表
   */
  async findAll(query: OcrQueryDto): Promise<OcrTaskPaginationResult> {
    const { page = 1, pageSize = 10, url, taskId, taskType, status } = query

    // 构建查询条件
    const whereConditions: any = { isDelete: 0 }

    if (url) {
      whereConditions.url = url
    }

    if (taskId) {
      whereConditions.taskId = taskId
    }

    if (taskType !== undefined) {
      whereConditions.taskType = taskType
    }

    if (status !== undefined) {
      whereConditions.status = status
    }

    // 查询总数
    const total = await this.ocrTaskRepository.count({ where: whereConditions })

    // 查询分页数据
    const items = await this.ocrTaskRepository.find({
      where: whereConditions,
      skip: (page - 1) * pageSize,
      take: pageSize,
      order: { createdAt: 'DESC' },
    })

    return {
      items,
      total,
      page,
      pageSize,
    }
  }
}
